/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package MIPS;

import java.util.Locale;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Keiner - jorgue
 */
public class EtapaIF extends Etapa {
    //public EtapaIF(int i, )

    private Cache instrucciones;
    private int PC = 0;
    private boolean cambio = false;
    private boolean enviada = false;
    private int[] IR = new int[4];
    private int VOLVER = -2;

    public EtapaIF(pizarra izquierda, pizarra derecha, Semaphore semaphore, Semaphore principal, Cache cacheInstrucciones) {
        super(0, izquierda, derecha, semaphore, principal);
        instrucciones = cacheInstrucciones;
    }

    public void setPC(int pc) {
        this.PC = pc;
    }

    public void setCambio(boolean cambio) {
        this.cambio = cambio;
    }

    @Override
    public void run() {
        while (true) {
            try {
                organizador.acquire();
                if (!atrasado) {
                    if (!cambio || (instrucciones.getRetraso() > 0 || !enviada)) { //cambio --> retraso
                        instrucciones.getSem().acquire();
                        IR = instrucciones.deme(this.PC);
                        if (instrucciones.getRetraso() == 0) {
                            esperar = true;  
                            while (esperar) {
                                synchronized (derecha) {
                                    derecha.lock();
                                    if (derecha.getCopiado()) {
                                        esperar = false;
                                        if (derecha.getPC() != PC - 4 && derecha.getPC() != -1 && derecha.getPC() != -2) { // revisa si hubo branche o jump
                                            this.PC = derecha.getPC();
                                            IR = instrucciones.deme(this.PC);
                                            derecha.setPC(VOLVER);
                                            enviada = false;
                                        } else {
                                            derecha.setPC(this.PC);
                                            derecha.setIR(IR);
                                            derecha.setCambio(cambio);
                                            enviada = true;
                                            System.out.printf("PC: " + PC);
                                            this.PC += 4;
                                            if (IR != null) {
                                                System.out.println("Código instrucción: " + IR[0]);      
                                            }
                                        }
                                        //derecha.setCopiado(true);
                                    }
                                    derecha.unLock();
                                }
                            }

                        }
                        instrucciones.getSem().release();
                    }
                }else{
                    if(instrucciones.getRetraso() > 0){
                        instrucciones.cambioCiclo();
                    }else{
                        enviada = false;
                    }
                }
                principal.release();
            } catch (InterruptedException ex) {
                Logger.getLogger(EtapaIF.class.getName()).log(Level.SEVERE, null, ex);
            }

        }

    }

    public static boolean XOR(boolean x, boolean y) {
        return ((x || y) && !(x && y));
    }
}
